#pragma once
#include "abstract.hpp"
#include "fields.hpp"
#include "detail.hpp"

namespace bitrpc
{
    class JsonMessage : public BaseMessage
    {
    public:
        using ptr = std::shared_ptr<JsonMessage>;

        virtual std::string Serialize() override // 序列化
        {
            std::string body;
            bool ret = JSON::Serialize(_body, body);
            if (ret == false)
            {
                return "";
            }
            return body;
        }
        virtual bool DeSerialize(std::string &msg) override // 反序列化
        {
            return JSON::Deserialize(msg, _body);
        }

    protected:
        Json::Value _body;
    };
    class JsonRequest : public JsonMessage
    {
    public:
        using ptr = std::shared_ptr<JsonRequest>;
    };
    class JsonResponse : public JsonMessage
    {
    public:
        using ptr = std::shared_ptr<JsonResponse>;
        virtual bool check() override // 进行消息检查
        {
            // 在响应中，大部分的响应都有响应状态码
            // 因此只需要判断状态码是否存在，以及类型是否正确
            if (_body[KEY_RCODE].isNull() == true)
            {
                ELOG("响应中没有响应状态码!");
                return false;
            }
            else if (_body[KEY_RCODE].isIntegral() == false)
            {
                ELOG("响应状态码类型错误!");
                return false;
            }
            return true;
        }
         RCODE rcode()
        {
            return (RCODE)_body[KEY_RCODE].asInt();
        }
        void setRcode(RCODE rcode)
        {
            _body[KEY_RCODE] = (int)rcode;
        }
    };
    class RPCRequest : public JsonRequest
    {
    public:
        using ptr = std::shared_ptr<RPCRequest>;
        virtual bool check() override
        {
            // rpc请求中，包含请求方法名称——字符串，参数字段——对象
            if (_body[KEY_METHOD].isNull() == true ||
                _body[KEY_METHOD].isString() == false)
            {
                ELOG("RPC请求中没有方法名称或方法名称类型错误!");
                return false;
            }
            if (_body[KEY_PARAMS].isNull() ||
                _body[KEY_PARAMS].isObject() == false)
            {
                ELOG("RPC请求中没有参数信息或参数信息类型错误!");
                return false;
            }
            return true;
        }
        std::string method()
        {
            return _body[KEY_METHOD].asString();
        }
        void SetMethod(const std::string &method_name)
        {
            _body[KEY_METHOD] = method_name;
        }
        Json::Value params()
        {
            return _body[KEY_PARAMS];
        }
        void SetParams(const Json::Value &params)
        {
            _body[KEY_PARAMS] = params;
        }
    };
    class TopicRequest : public JsonRequest
    {
    public:
        using ptr = std::shared_ptr<TopicRequest>;
        virtual bool check() override
        {
            // Topic请求中，包含主题名称——字符串，操作类型——int
            if (_body[KEY_TOPIC_KEY].isNull() == true ||
                _body[KEY_TOPIC_KEY].isString() == false)
            {
                ELOG("主题请求中没有主题名称或主题名称类型错误!");
                return false;
            }
            if (_body[KEY_OPTYPE].isNull() ||
                _body[KEY_OPTYPE].isIntegral() == false)
            {
                ELOG("主题请求中没有操作类型或操作类型的类型错误!");
                return false;
            }
            if (_body[KEY_OPTYPE].asInt() == (int)TopicOptype::TOPIC_PUBLISH && (_body[KEY_TOPIC_MSG].isNull() || _body[KEY_TOPIC_MSG].isString() == false))
            {
                ELOG("主题消息发布请求中没有消息内容字段或消息内容的类型错误!");
                return false;
            }
            return true;
        }
        std::string TopicKey()
        {
            return _body[KEY_TOPIC_KEY].asString();
        }
        void setTopicKey(const std::string &topickey)
        {
            _body[KEY_TOPIC_KEY] = topickey;
        }
        TopicOptype topicOptype()
        {
            return (TopicOptype)_body[KEY_OPTYPE].asInt();
        }
        void setTopicOptype(TopicOptype optype)
        {
            _body[KEY_OPTYPE] = (int)optype;
        }
        std::string topicMsg()
        {
            return _body[KEY_TOPIC_MSG].asString();
        }
        void setTopicMsg(const std::string &msg)
        {
            _body[KEY_TOPIC_MSG] = msg;
        }
    };
    using Address = std::pair<std::string, int>;
    class ServiceRequest : public JsonRequest
    {
    public:
        using ptr = std::shared_ptr<ServiceRequest>;
        virtual bool check() override
        {
            // 服务请求中，包含请求方法名称——字符串，操作类型——int，主机地址信息
            if (_body[KEY_METHOD].isNull() == true ||
                _body[KEY_METHOD].isString() == false)
            {
                ELOG("服务请求中没有方法名称或方法名称类型错误!");
                return false;
            }
            if (_body[KEY_OPTYPE].isNull() ||
                _body[KEY_OPTYPE].isIntegral() == false)
            {
                ELOG("服务请求中没有操作类型或操作类型的类型错误!");
                return false;
            }
            //如果是服务发现请求，就没有host信息
            if (_body[KEY_OPTYPE] != (int)ServiceOptype::SERVICE_DISCOVERY &&
                (_body[KEY_HOST].isNull() || _body[KEY_HOST].isObject() == false || _body[KEY_HOST][KEY_HOST_IP].isNull() || _body[KEY_HOST][KEY_HOST_IP].isString() == false || _body[KEY_HOST][KEY_HOST_PORT].isNull() || _body[KEY_HOST][KEY_HOST_PORT].isIntegral() == false))
            {
                ELOG("服务消息发布请求中没有主机地址内容字段或主机地址内容的类型错误!");
                return false;
            }
            return true;
        }
        std::string method()
        {
            return _body[KEY_METHOD].asString();
        }
        void setMethod(const std::string &name)
        {
            _body[KEY_METHOD] = name;
        }
       
        ServiceOptype serviceOptype()
        {
            return (ServiceOptype)_body[KEY_OPTYPE].asInt();
        }
        void setServiceOptype(ServiceOptype optype)
        {
            _body[KEY_OPTYPE] = (int)optype;
        }
        Address host()
        {
            Address addr;
            addr.first = _body[KEY_HOST][KEY_HOST_IP].asString();
            addr.second = _body[KEY_HOST][KEY_HOST_PORT].asInt();
            return addr;
        }
        void setHost(const Address &addr)
        {
            Json::Value val;
            val[KEY_HOST_IP] = addr.first;
            val[KEY_HOST_PORT] = addr.second;
            _body[KEY_HOST] = val;
        }
    };
    class RpcResponse : public JsonResponse
    {
    public:
        using ptr = std::shared_ptr<RpcResponse>;
        // rpc应答中含有状态码和运行结果
        virtual bool check() override
        {
            if (_body[KEY_RCODE].isNull() == true || _body[KEY_RCODE].isIntegral() == false)
            {
                ELOG("rpc响应中没有响应状态码或响应状态码类型错误！");
                return false;
            }
            if (_body[KEY_RESULT].isNull())
            {
                ELOG("rpc响应中没有运行结果!");
                return false;
            }
            return true;
        }

       
        Json::Value result()
        {
            return _body[KEY_RESULT];
        }
        void setResult(const Json::Value &result)
        {
            _body[KEY_RESULT] = result;
        }
    };
    class TopicResponse : public JsonResponse
    {
    public:
        using ptr = std::shared_ptr<TopicResponse>;
        // Topic应答中只含有状态码

      
    };
    class ServiceResponse : public JsonResponse
    {
    public:
        using ptr = std::shared_ptr<ServiceResponse>;
        // 如果是注册+上线下线功能：Topic应答只含有状态码和操作类型
        //如果是服务发现功能，则含有rcode，操作类型，方法名称，和地址信息
        //操作类型是用来区分响应功能的
        virtual bool check() override
        {
            if (_body[KEY_RCODE].isNull() == true || _body[KEY_RCODE].isIntegral() == false)
            {
                ELOG("服务响应中没有响应状态码或响应状态码类型错误！");
                return false;
            }
            
            //如果是服务发现功能
            if(_body[KEY_OPTYPE] == (int)ServiceOptype::SERVICE_DISCOVERY&&
            (_body[KEY_METHOD].isNull() || _body[KEY_METHOD].isString()==false)||
            _body[KEY_HOST].isNull() ||  _body[KEY_HOST].isArray()==false)
            {
               ELOG("服务发现响应信息字段错误！");
                return false;
            }
            return true;
        }
       
          ServiceOptype serviceOptype()
        {
            return (ServiceOptype)_body[KEY_OPTYPE].asInt();
        }
        void setServiceOptype(ServiceOptype optype)
        {
            _body[KEY_OPTYPE] = (int)optype;
        }
        std::string method()
        {
            return _body[KEY_METHOD].asString();
        }
        void setMethod(std::string method)
        {
            _body[KEY_METHOD]=method;
        }
        void setHost(std::vector<Address> addrs)
        {
            for(auto &cur:addrs)
            {
                Json::Value val;
                val[KEY_HOST_IP]=cur.first;
                val[KEY_HOST_PORT]=cur.second;
                _body[KEY_HOST].append(val);
            }
        }
        std::vector<Address> hosts()
        {
            std::vector<Address>addrs;
            int sz = _body[KEY_HOST].size();
            for(int i=0;i<sz;i++)
            {
                Address addr;
                addr.first = _body[KEY_HOST][i][KEY_HOST_IP].asString();
                addr.second = _body[KEY_HOST][i][KEY_HOST_PORT].asInt();
                addrs.push_back(addr);
            }
            return addrs;
        }

    };
    //构建一个消息对象的生产工厂，可以通过这个函数创建出各种消息对象，不需要自己手动创建（维护起来麻烦），可维护性和扩展性强
    class MessageFactory
    {
      public:
      static BaseMessage::ptr create(MessageType  mtype)
      {
           switch(mtype)
           {
            case MessageType::REQ_RPC :return std::make_shared<RPCRequest>();
            case MessageType::RSP_RPC :return std::make_shared<RpcResponse>();
            case MessageType::REQ_TOPIC :return std::make_shared<TopicRequest>();
            case MessageType::RSP_TOPIC :return std::make_shared<TopicResponse>();
            case MessageType::REQ_SERVICE :return std::make_shared<ServiceRequest>();
            case MessageType::RSP_SERVICE :return std::make_shared<ServiceResponse>();
           }
           return BaseMessage::ptr();
      }
      template<typename T, typename ...Args> 
      static std::shared_ptr<T> create(Args&& ...args) { 
       return std::make_shared<T>(std::forward<Args>(args)...); 
      }
   
    };
    
}